﻿namespace HostTracker.Azure.Management

open System
open System.ServiceModel
open System.ServiceModel.Web
open System.Runtime.Serialization
open FSharpExtensions
(*
<?xml version="1.0" encoding="utf-8"?>
  <AffinityGroups xmlns="http://schemas.microsoft.com/windowsazure">
    <AffinityGroup>
      <Name>affinity-group-name</Name>
      <Label>base64-encoded-label</Label>
      <Description>description</Description>
      <Location>location</Location>  
    </AffinityGroup>  
          …
  </AffinityGroups>
*)
[<DataContract(Name = "AffinityGroup", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type AffinityGroup() =
    let mutable name = ""
    let mutable label = ""
    let mutable desc = ""
    let mutable loc = ""
    [<DataMember(Name = "Name", Order = 1)>]
    member x.Name with get () = name and set v = name <- v
    [<DataMember(Name = "Label", Order = 2)>]
    member private x.LabelEncoded with get () = label.ToBase64() and set (v: string) = label <- v.FromBase64()
    member x.Label with get () = label and set v = label <- v
    [<DataMember(Name = "Description", Order = 3)>]
    member x.Desc with get () = desc and set v = desc <- v
    [<DataMember(Name = "Location", Order = 4)>]
    member x.Location with get () = loc and set v = loc <- v

[<DataContract(Name = "AffinityGroup", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type AffinityGroupExtended() = 
    inherit AffinityGroup()
    let mutable hostedServices = HostedServices()
    [<DataMember(Name = "HostedServices", Order = 4)>]
    member x.Services with get () = hostedServices and set v = hostedServices <- v

[<CollectionDataContract(Name = "AffinityGroups", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type AffinityGroups() = inherit System.Collections.Generic.List<AffinityGroup>()

(*
<?xml version="1.0" encoding="utf-8"?>
<CreateAffinityGroup xmlns="http://schemas.microsoft.com/windowsazure">
      <Name>affinity-group-name</Name>
      <Label>base64-encoded-affinity-group-label</Label>
      <Description>affinity-group-description</Description>
      <Location>location</Location>
</CreateAffinityGroup>
*)
[<DataContract(Name = "CreateAffinityGroup", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type AffinityGroupCreation() = inherit AffinityGroup()

(*
<?xml version="1.0" encoding="utf-8"?>
<UpdateAffinityGroup xmlns="http://schemas.microsoft.com/windowsazure">
      <Label>base64-encoded-affinity-group-label</Label>
      <Description>affinity-group-description</Description>
</UpdateAffinityGroup>
*)
[<DataContract(Name = "UpdateAffinityGroup", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type AffinityGroupUpdate(label: string, desc: string) = 
    [<DataMember(Name = "Label", Order = 1)>]
    member private x.LabelEncoded with get () = label.ToBase64() and set _ = ()
    [<DataMember(Name = "Description", Order = 2)>]
    member private x.Desc with get () = desc and set _ = ()

(*
<?xml version="1.0" encoding="utf-8"?>
<Locations xmlns=”http://schemas.microsoft.com/windowsazure”>
  <Location>
    <Name>location-name</Name>
    <DisplayName>localized-location-name</DisplayName>
  </Location>
     …
</Locations>
*)
[<DataContract(Name = "Location", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type Location() = 
    let mutable name = ""
    let mutable displayName = ""
    [<DataMember(Name = "Name", Order = 1)>]
    member x.Name with get() = name and set v = name <- v
    [<DataMember(Name = "DisplayName", Order = 2)>]
    member x.DisplayName with get() = displayName and set v = displayName <- v

[<CollectionDataContract(Name = "Locations", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type Locations() = inherit System.Collections.Generic.List<Location>()

[<Interface>]
[<ServiceContractAttribute>]
type IAffinityGroupManagement =
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/affinitygroups", Method="GET")>]
    abstract ListAffinityGroups: unit -> AffinityGroups
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/affinitygroups/{groupName}", Method="GET")>]
    abstract GetAffinityGroup: groupName:string -> AffinityGroupExtended
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/affinitygroups", Method="POST")>]
    abstract CreateAffinityGroup: creation: AffinityGroupCreation -> unit
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/affinitygroups/{groupName}", Method="DELETE")>]
    abstract DeleteAffinityGroup: groupName:string -> unit
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/affinitygroups/{groupName}", Method="PUT")>]
    abstract UpdateAffinityGroup: groupName:string*updating: AffinityGroupUpdate -> unit
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/locations", Method="GET")>]
    abstract ListLocations: unit -> Locations

    (* async methods *)
    [<OperationContract(AsyncPattern=true)>]
    abstract BeginListAffinityGroups: callback:AsyncCallback*asyncState:obj -> IAsyncResult //AffinityGroups    
    abstract EndListAffinityGroups: result: IAsyncResult -> AffinityGroups

    [<OperationContract(AsyncPattern=true)>]
    abstract BeginGetAffinityGroup: groupName:string*callback:AsyncCallback*asyncState:obj -> IAsyncResult
    abstract EndGetAffinityGroup: result: IAsyncResult -> AffinityGroupExtended

    [<OperationContract(AsyncPattern=true)>]
    abstract BeginCreateAffinityGroup: creation: AffinityGroupCreation*callback:AsyncCallback*asyncState:obj -> IAsyncResult
    abstract EndCreateAffinityGroup: result: IAsyncResult -> unit

    [<OperationContract(AsyncPattern=true)>]
    abstract BeginDeleteAffinityGroup: groupName:string*callback:AsyncCallback*asyncState:obj -> IAsyncResult
    abstract EndDeleteAffinityGroup: result: IAsyncResult -> unit

    [<OperationContract(AsyncPattern=true)>]
    abstract BeginUpdateAffinityGroup: groupName:string*updating: AffinityGroupUpdate*callback:AsyncCallback*asyncState:obj -> IAsyncResult
    abstract EndUpdateAffinityGroup: result: IAsyncResult -> unit

    [<OperationContract(AsyncPattern=true)>]
    abstract BeginListLocations: callback:AsyncCallback*asyncState:obj -> IAsyncResult
    abstract EndListLocations: result: IAsyncResult -> Locations